package com.example.flutter_demo

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.StandardMessageCodec
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.ConcurrentHashMap


class MainActivity : FlutterActivity() {

    private var functionCallTimes = 0;
    private var methodCall = 0;

    private val timeListener = ConcurrentHashMap<Any?, EventChannel.EventSink?>()

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        handleTypeTest(flutterEngine)
        handleMethodCall(flutterEngine)
        handleTimeListener(flutterEngine)
    }

    private fun handleTimeListener(flutterEngine: FlutterEngine) {
        val eventChannel = EventChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "com.example.flutter_demo/timeChanged"
        )
        eventChannel.setStreamHandler(
            object : EventChannel.StreamHandler {
                private var cycleReportJob: Job? = null

                override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                    //有终端订阅
                    timeListener[arguments] = events
                    //若为粘性事件，将在订阅的第一时间返回最后一个值
                    events?.success(System.currentTimeMillis())
                    startCycleReport()
                }


                override fun onCancel(arguments: Any?) {
                    //有终端取消订阅
                    timeListener.remove(arguments)
                    if (timeListener.isEmpty()) {
                        stopCycleReport()
                    }
                }

                private fun startCycleReport() {
                    if (cycleReportJob != null && cycleReportJob?.isActive == true) {
                        return
                    }
                    cycleReportJob = CoroutineScope(Dispatchers.IO).launch {
                        val adjust = System.currentTimeMillis() % 1000
                        if (adjust != 0L) {
                            delay(1000 - adjust)
                        }
                        while (isActive) {
                            withContext(Dispatchers.Main) {
                                timeListener.values.forEach {
                                    it?.success(System.currentTimeMillis())
                                }
                            }
                            delay(1000)
                        }
                    }
                }

                private fun stopCycleReport() {
                    cycleReportJob?.run {
                        cancel()
                        cycleReportJob = null
                    }
                }
            }
        )
    }

    private fun handleMethodCall(flutterEngine: FlutterEngine) {
        val methodChannel = MethodChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "com.example.flutter_demo/method_call"
        )
        methodChannel.setMethodCallHandler { call, result ->
            when (call.method) {
                "getValue" -> result.success(methodCall)
                "add" -> {
                    val addValue = call.arguments
                    if (addValue is Int) {
                        methodCall += addValue
                        result.success(methodCall)
                    } else {
                        result.error("1001", "参数异常", "")
                    }
                }

                else -> result.notImplemented()
            }
        }
    }

    private fun handleTypeTest(flutterEngine: FlutterEngine) {
        val typeTest = BasicMessageChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "com.example.flutter_demo/type_test",
            StandardMessageCodec()
        )
        typeTest.setMessageHandler { message, reply ->
            if (message is HashMap<*, *>) {
                reply.reply(
                    """
                    platform：Android
                    "bool": ${message["bool"]},
                    "int": ${message["int"]},
                    "long": ${message["long"]},
                    "double":${message["double"]},
                    "String": ${message["String"]},
                    "Uint8List":${
                        (message["Uint8List"] as ByteArray).joinToString(
                            ",",
                            prefix = "[",
                            postfix = "]"
                        )
                    },
                    "Int32List":${
                        (message["Int32List"] as IntArray).joinToString(
                            ",",
                            prefix = "[",
                            postfix = "]"
                        )
                    },
                    "Int64List": ${
                        (message["Int64List"] as LongArray).joinToString(
                            ",",
                            prefix = "[",
                            postfix = "]"
                        )
                    },
                    "Float32List": ${
                        (message["Float32List"] as FloatArray).joinToString(
                            ",",
                            prefix = "[",
                            postfix = "]"
                        )
                    },
                    "Float64List":${
                        (message["Float64List"] as DoubleArray).joinToString(
                            ",",
                            prefix = "[",
                            postfix = "]"
                        )
                    },
                    "List": ${message["List"]},
                    "Map": ${message["Map"]},
                          """.trimIndent()
                )
                typeTest.send(++functionCallTimes);
            } else {
                throw IllegalArgumentException("参数异常：com.example.flutter_demo/type_test(${message.toString()})")
            }
        }
    }

}
